import { cloneDeep, isEqual } from 'lodash-es';
import { MODEL_NAME } from '../../constants/model-names';
import type { BaseSnapshot } from '../../systems/save';
import { BaseModel } from '../base';
import { EVENTS, type IEventBus } from '../../events';
import type {
  OfflineEarningsRealmInfo,
  OflineEarningsSectHangUpTaskInfo,
} from './type';

type EarningsMap = {
  /** 修为 */
  realm: { value: number };
  /** 宗门贡献 */
  sectContribution: { value: number };
  /** 灵石 */
  spiritualStone: { value: number };
};

interface OfflineEarningsV1 extends BaseSnapshot {
  version: 1;
  offlineTime: number;
}

export type OfflineEarningsSnapshot = OfflineEarningsV1;
export type OfflineEarningsSnapshotOld = OfflineEarningsV1;

const defaultEarnings: EarningsMap = {
  realm: {
    value: 0,
  },
  sectContribution: {
    value: 0,
  },
  spiritualStone: {
    value: 0,
  },
};

const defaultRealmInfo: OfflineEarningsRealmInfo = {
  consumeSectCultivationSpotCount: 0,
  sectCultivationSpotValidCount: 0,
  consumeSectCultivationSpotCountExp: 0,
  cultivationKillsExp: 0,
};

const defaultSectHangUpTaskInfo: OflineEarningsSectHangUpTaskInfo = {
  sectContribution: 0,
  spiritualStone: 0,
};

export class OfflineEarningsModel extends BaseModel {
  public name = MODEL_NAME.OFFLINE_EARNINGS;
  private bus: IEventBus;
  private readonly MAX_OFFLINE = 24 * 3600 * 1000;
  /** 离线时间 */
  private offlineTime = 0;
  /** 保存离线收益，用于展示 */
  private earnings: EarningsMap = cloneDeep(defaultEarnings);
  /** 修为相关回显信息 */
  private realmInfo: OfflineEarningsRealmInfo = cloneDeep(defaultRealmInfo);
  /** 宗门挂机任务相关回显信息 */
  private sectHangUpTaskInfo: OflineEarningsSectHangUpTaskInfo = cloneDeep(
    defaultSectHangUpTaskInfo
  );

  constructor(bus: IEventBus) {
    super();
    this.bus = bus;
  }

  /** 设置离线时间 */
  public setOfflineTime(time: number) {
    if (!isEqual(this.earnings, defaultEarnings)) return;
    this.offlineTime = time;
  }

  public setRealmEarnings(value: number) {
    this.earnings.realm.value = value;
    this.bus.emit(EVENTS.OFFLINE_EARNINGS_STATE_UPDATE);
  }

  public setSectContribution(value: number) {
    this.earnings.sectContribution.value = value;
    this.bus.emit(EVENTS.OFFLINE_EARNINGS_STATE_UPDATE);
  }

  public setSpiritualStone(value: number) {
    this.earnings.spiritualStone.value = value;
    this.bus.emit(EVENTS.OFFLINE_EARNINGS_STATE_UPDATE);
  }

  public getOfflineDiffTime() {
    if (this.offlineTime === 0) return 0;
    const diff = Date.now() - this.offlineTime;
    return Math.min(this.MAX_OFFLINE, Math.max(1000, diff));
  }

  public resetEarnings() {
    this.earnings = cloneDeep(defaultEarnings);
    this.bus.emit(EVENTS.OFFLINE_EARNINGS_STATE_UPDATE);
  }

  public getEarnings() {
    return cloneDeep(this.earnings);
  }

  /** 是否有离线收益 */
  public hasEarnings() {
    return !isEqual(this.earnings, defaultEarnings);
  }

  /** 设置修为相关回显信息 */
  public setRealmInfo(info: OfflineEarningsRealmInfo) {
    this.realmInfo = info;
    this.bus.emit(EVENTS.OFFLINE_EARNINGS_STATE_UPDATE);
  }

  /** 获取修为相关回显信息 */
  public getRealmInfo() {
    return cloneDeep(this.realmInfo);
  }

  /** 设置宗门挂机任务相关回显信息 */
  public setSectHangUpTaskInfo(info: OflineEarningsSectHangUpTaskInfo) {
    this.sectHangUpTaskInfo = info;
    this.bus.emit(EVENTS.OFFLINE_EARNINGS_STATE_UPDATE);
  }

  /** 获取宗门挂机任务相关回显信息 */
  public getSectHangUpTaskInfo() {
    return cloneDeep(this.sectHangUpTaskInfo);
  }

  public get uiState() {
    return {
      showInfo: !isEqual(this.earnings, defaultEarnings),
      offlineTime: this.getOfflineDiffTime(),
      earnings: cloneDeep(this.earnings),
      realmInfo: this.getRealmInfo(),
      sectHangUpTaskInfo: this.getSectHangUpTaskInfo(),
    };
  }

  public save(): OfflineEarningsSnapshot {
    return {
      version: 1,
      offlineTime: this.offlineTime,
    };
  }

  public load(snapshot: OfflineEarningsSnapshot): void {
    this.offlineTime = snapshot.offlineTime || Date.now();
  }
}
